import math

#Basic implementation for a point
class Point(object):
    def __init__(self, x, y):
        self._x, self._y = float(x), float(y)
        self._next = None
        self._previous = None
    def __str__(self):
        tag = " " + self.tag if self.tag != "" else ""
        return "<" + self.__class__.__name__ + tag + " (%s, %s)>" % (str(self._x), str(self._y))
    def __repr__(self):
        tag = " " + self.tag if self.tag != "" else ""
        return "<" + self.__class__.__name__ + tag + " (%s, %s)>" % (str(self._x), str(self._y))
    @property
    def tag(self):
        return ""
    @property
    def x(self):
        return self._x
    @property
    def y(self):
        return self._y
    def __eq__(self, other):
        assert isinstance(other, Point)
        return (self.x == other.x) and (self.y == other.y)
    def __add__(self, other):
        assert isinstance(other, Point)
        return Point(self.x + other.x, self.y + other.y)
    def __sub__(self, other):
        assert isinstance(other, Point)
        return Point(self.x - other.x, self.y - other.y)
    def __div__(self, ratio):
        assert isinstance(ratio, float) or isinstance(ratio, int)
        return Point(self.x / float(ratio), self.y / float(ratio))
    def __mul__(self, ratio):
        assert isinstance(ratio, float) or isinstance(ratio, int)
        return Point(self.x * float(ratio), self.y * float(ratio))
    @property
    def radius(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)
    @property
    def angle(self):
        return math.atan2(self.y, self.x) % (2 * math.pi)
    @property
    def unit_point(self):
        return UnitCirclePoint(self)
    @property
    def next(self):
        return self._next
    @property
    def previous(self):
        return self._previous
    def setNext(self, next):
        assert isinstance(next, Point)
        self._next = next
        next._previous = self
    def __cmp__(self, other):
        if not (other):
            return 1
        return cmp(self.angle, other.angle)

#Basic implementation for a point on a unit circle
class UnitCirclePoint(Point):
    def __init__(self, original):
        Point.__init__(self, math.cos(original.angle), math.sin(original.angle))
        self._original = original
    @property
    def original(self):
        return self._original
